package vip.liux.contracts.repositories.messaging;

import org.jetbrains.annotations.NotNull;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.util.ReflectionUtils;
import vip.liux.contracts.models.notification.MessageTask;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public interface MessageTaskRepository extends ListCrudRepository<MessageTask, Long> {
    MessageTaskRepository INSTANCE = new InMemoryNotificationMessageRepository();

    class InMemoryNotificationMessageRepository implements MessageTaskRepository {
        private final Map<Long, MessageTask> storage = new ConcurrentHashMap<>();

        private long idCounter = 1;

        @Override
        public <S extends MessageTask> @NotNull S save(S entity) {
            if (entity.getId() == null) {
                ReflectionUtils.invokeMethod(
                        Objects.requireNonNull(ReflectionUtils.findMethod(MessageTask.class, "setId", Long.class)),
                        entity,
                        idCounter++
                );
            }
            storage.put(entity.getId(), entity);
            return entity;
        }

        @Override
        public @NotNull Optional<MessageTask> findById(@NotNull Long id) {
            return Optional.ofNullable(storage.get(id));
        }

        @Override
        public boolean existsById(@NotNull Long id) {
            return storage.containsKey(id);
        }

        @Override
        public <S extends MessageTask> @NotNull List<S> saveAll(@NotNull Iterable<S> entities) {
            return List.of();
        }

        @Override
        public @NotNull List<MessageTask> findAll() {
            return storage.values().stream().toList();
        }

        @Override
        public @NotNull List<MessageTask> findAllById(Iterable<Long> ids) {
            List<MessageTask> result = new ArrayList<>();
            for (Long id : ids) {
                if (storage.containsKey(id)) {
                    result.add(storage.get(id));
                }
            }
            return result;
        }

        @Override
        public long count() {
            return storage.size();
        }

        @Override
        public void deleteById(@NotNull Long id) {
            storage.remove(id);
        }

        @Override
        public void delete(MessageTask entity) {
            storage.remove(entity.getId());
        }

        @Override
        public void deleteAllById(Iterable<? extends Long> ids) {
            for (Long id : ids) {
                storage.remove(id);
            }
        }

        @Override
        public void deleteAll(Iterable<? extends MessageTask> entities) {
            for (MessageTask entity : entities) {
                storage.remove(entity.getId());
            }
        }

        @Override
        public void deleteAll() {
            storage.clear();
        }
    }
}